package cc.rengu.igas.share.core.service.trans;

import cc.rengu.igas.channel.wechat.facade.request.CancelMsgPushRequest;
import cc.rengu.igas.channel.wechat.facade.request.FinancialTransMsgPushRequest;
import cc.rengu.igas.channel.wechat.facade.request.RefundMsgPushRequest;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.constant.ShareTreeNodeConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.common.dao.BspsUserInfoMapper;
import cc.rengu.igas.share.common.dao.impl.BspsUserInfoMapperImpl;
import cc.rengu.igas.share.common.entity.BspsUserInfo;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.common.util.SensitiveDataUtil;
import cc.rengu.igas.share.core.model.*;
import cc.rengu.igas.share.core.realize.BspsService;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.BspsServiceImpl;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.igas.smps.facade.base.Header;
import cc.rengu.igas.smps.facade.request.*;
import cc.rengu.igas.smps.facade.response.GeneralSmsNoticeResponse;
import cc.rengu.igas.smps.facade.result.Result;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.TxnNoticeInfoMapper;
import cc.rengu.oltp.service.common.dao.UserOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.TxnNoticeInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.UserOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.PayTypeEnum;
import cc.rengu.oltp.service.common.enums.TransTypeEnum;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class MchntTransNoticeService extends RadpService {
    @Override
    protected int bizInit(String s) {
        return 0;
    }

    @Override
    protected int bizProcess(String s, int i) {
        try {
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
            String respDesc = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.RESP_DESC);

            /* 获取用户订单信息 */
            UserOrderInfo userOrderInfo = (UserOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.USER_ORDER_INFO);
            if (null == userOrderInfo) {
                UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
                String userOrderId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.USER_ORDER_ID);
                userOrderInfo = userOrderInfoMapper.selectUserOrderInfoByUserOrderId(instId, userOrderId);
                if (null == userOrderInfo) {
                    String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
                    userOrderInfo = userOrderInfoMapper.selectUserOrderInfoByPrimaryKey(instId, sysSeqNum);
                    if (null == userOrderInfo) {
                        rglog.warn("用户订单信息不存在，instId:<{}>,userOrderId:<{}>,sysSeqNum:<{}>", instId, userOrderId, sysSeqNum);
                        return -1;
                    }
                }
            }

            /* 获取商户订单信息 */
            List<MchntOrderInfo> mchntOrderInfoList = (List<MchntOrderInfo>) GlobalTransUtil.getCacheValue(TransCacheConstant.MCHNT_ORDER_INFO_LIST);
            if (null == mchntOrderInfoList || mchntOrderInfoList.isEmpty()) {
                MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
                mchntOrderInfoList = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(instId, userOrderInfo.getSysSeqNum());
                if (null == mchntOrderInfoList || mchntOrderInfoList.isEmpty()) {
                    rglog.warn("根据支付交易的系统流水号{}查询商户订单信息失败！", userOrderInfo.getSysSeqNum());
                    return -2;
                }
            }

            /* 获取交易配置信息 */
            String txnPattern = userOrderInfo.getTxnNum().trim() + userOrderInfo.getBizType().trim();
            Map<String, String> keyValueMap = RedisUtil.hashGetAll(AppParamConstant.TXN_INFO_CACHE);
            Optional<String> txnKeyOpt = keyValueMap.keySet().stream().filter(item -> item.contains(txnPattern)).findFirst();
            TxnInfo txnInfo = txnKeyOpt.map(value -> JSON.parseObject(keyValueMap.get(value), TxnInfo.class)).orElse(null);
            if (null == txnInfo || null == txnInfo.getSrcTxnAuthCfg()) {
                rglog.warn("交易配置信息不存在,不进行交易结果异步推送,instId:<{}>,txnNum:<{}>,bizType:<{}>",
                        userOrderInfo.getInstId().trim(), userOrderInfo.getTxnNum().trim(), userOrderInfo.getBizType().trim());
                return -3;
            }

            /* 将txnInfo放到节点中,微信公众号推送失败时发送短信需要使用到该txnInfo */
            xmlTreeUtil.setXmlTreeObjectValue(TreeNodeConstant.TXN_INFO, txnInfo);

            /* 获取支付订单信息 */
            PayOrderInfo payOrderInfo = (PayOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.PAY_ORDER_INFO);
            if (null == payOrderInfo) {
                PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
                List<PayOrderInfo> payOrderInfoList = payOrderInfoMapper.selectPayOrderInfoBySysSeqNum(instId, userOrderInfo.getSysSeqNum());
                if (null == payOrderInfoList || payOrderInfoList.isEmpty()) {
                    rglog.warn("用户订单及支付订单不存在!");
                    return -1;
                }
                /* 获取主体支付方 */
                Predicate<PayOrderInfo> d0Filter1 = p -> !ShareParamConstant.SUB_SYS_ID_D0_REALTIME.equals(p.getChannelBizType());
                Predicate<PayOrderInfo> d0Filter2 = p -> !ShareParamConstant.OTHER_SUB_SYS_ID_D0_REALTIME.equals(p.getChannelBizType());
                payOrderInfoList = payOrderInfoList.stream().filter(d0Filter1.and(d0Filter2))
                        .sorted(Comparator.comparing(PayOrderInfo::getDstCallIndex)).collect(Collectors.toList());
                Predicate<PayOrderInfo> acctFilter = p -> !ChannelEnum.ACCT.getChannelType().equals(p.getMsgDstId());
                Predicate<PayOrderInfo> mompFilter = p -> !ChannelEnum.MOMP.getChannelType().equals(p.getMsgDstId());
                Predicate<PayOrderInfo> mixScoreFilter = p -> !PayTypeEnum.SCORE.getPayType().equals(p.getPayType());
                List<PayOrderInfo> payOrderInfoListFilter = payOrderInfoList.stream().filter(acctFilter.and(mompFilter).and(mixScoreFilter)).collect(Collectors.toList());
                /* 判断是否存在商户D0实时入账的流水 */
                payOrderInfoListFilter = payOrderInfoListFilter.stream().filter(item -> !"D0".equals(item.getDstChannelType())).collect(Collectors.toList());
                if (payOrderInfoListFilter.size() > 1) {
                    rglog.info("当前交易存在多种主支付方式，请排查是否存在主支付方式过滤问题!");
                    return -4;
                }
                payOrderInfo = payOrderInfoListFilter.get(0);
            }

            /* 获取短信发送开送配置 */
            SysParamService sysParamService = new SysParamServiceImpl();
            SysParam sysParam = sysParamService.getSysParamInfo(instId, "SMS_SWITCH_PARAM", "SMS_SEND_FLAG");

            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                /* 将商户订单信息登记到内部树 */
                GlobalTransUtil.setCacheValue(TransCacheConstant.MCHNT_ORDER_INFO, mchntOrderInfo);
                /* 获取商户绑定关系 */
                BspsService bspsService = new BspsServiceImpl();
                List<MchntBindInfo> mchntBindInfoList = bspsService.getMchntBindInfo(instId, mchntOrderInfo.getUserId(), mchntOrderInfo.getMchntNo());
                if (!CollectionUtils.isEmpty(mchntBindInfoList)) {
                    if (StringUtil.isEmptyOrNull(mchntOrderInfo.getUserId())) {
                        //商户订单表中userId为空时，将消息推送给法人
                        mchntBindInfoList = mchntBindInfoList.stream().filter(item -> item.getBindUserRole().equals("00")).collect(Collectors.toList());
                    } else {
                        //商户订单表中userId不为空时，将消息推送给接收人，并查询绑定接收人
                        mchntBindInfoList = mchntBindInfoList.stream().filter(item -> item.getBindUserId().equals(mchntOrderInfo.getUserId())).collect(Collectors.toList());
                    }

                    /*获取商户绑定用户的openId*/
                    List<String> openIdList = new ArrayList<>();
                    List<String> pushUserList = convMsgPushUsers(mchntBindInfoList);
                    rglog.debug("商户<{}>在当前商户订单<{}>待推送消息通知的用户列表为:<{}>",mchntOrderInfo.getMchntNo(),mchntOrderInfo.getMchntOrderId(),JSON.toJSONString(pushUserList));
                    if (null != pushUserList && !pushUserList.isEmpty()) {
                        for (String userId : pushUserList) {
                            /* 获取用户信息 */
                            //TODO 先以查表的方式查询商户服务用户信息，待商户服务用户全部融合到统一用户服务组件后，启用下面注释掉的代码
                            BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
                            BspsUserInfo bspsUserInfo = bspsUserInfoMapper.selectBspsUserInfoByPrimaryKey(mchntOrderInfo.getInstId(),userId);
                            if (null != bspsUserInfo && !StringUtil.isEmptyOrNull(bspsUserInfo.getOpenId()) && !"OPENID".equals(bspsUserInfo.getOpenId().trim())){
                                openIdList.add(bspsUserInfo.getOpenId().trim());
                            }
//                            UserService userService = new UserServiceImpl();
//                            UserInfo userInfo = userService.getUserInfo(mchntOrderInfo.getInstId(), userId, xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SESSION));
//                            if (null != userInfo && null != userInfo.getUserApexMap()) {
//                                Map<String, String> userApexMap = userInfo.getUserApexMap();
//                                if (!"OPENID".equals(userApexMap.get("openId").trim())) {
//                                    openIdList.add(userApexMap.get("openId").trim());
//                                }
//                            }
                        }
                    }

                    /*区分商户是否绑定微信公众号，若没有绑定微信公众号则推送短信给商户的联系人*/
                    if (!openIdList.isEmpty()) {
                        /* 微信公众号通知 */
                        rglog.info("商户已经绑定公众号，通过绑定的用户的OPENID推送交易结果通知给商户");
                        mchntWechatNotice(mchntOrderInfo, openIdList, txnInfo, payOrderInfo);
                    } else {
                        rglog.info("商户绑定关系关系中消息推送人记录为空，给商户基本信息表中的商户联系人记录的手机号发送短信");
                        mchntSmsNotice(sysParam, mchntOrderInfo, txnInfo);
                    }
                } else {
                    rglog.info("商户没有在PC端注册，给商户基本信息表中的商户联系人记录的手机号发送短信");
                    mchntSmsNotice(sysParam, mchntOrderInfo, txnInfo);
                }

                /* 语音设备推送通知 */
                List<DevBindInfo> devBindInfoList = bspsService.getDevBindInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getUserId(), mchntOrderInfo.getMchntNo());
                if (null != devBindInfoList && !devBindInfoList.isEmpty()) {
                    /* 只推送推送开关为打开的设备 */
                    devBindInfoList = devBindInfoList.stream().filter(item -> AppParamConstant.YES.equals(item.getMsgPushFlag())).collect(Collectors.toList());
                    voiceDevNotice(mchntOrderInfo, devBindInfoList, payOrderInfo, txnInfo);
                }
            }
            /* 商户后台或商户服务服务H5页面通知 */
            String pushMsgContent = convMchntPushMsg(mchntOrderInfoList, payOrderInfo, respDesc, txnInfo, userOrderInfo);
            transResultNoticeToMchntSystem(userOrderInfo, pushMsgContent, txnInfo);
        } catch (Exception e) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            rglog.error("交易结果异步推送通知处理失败,异常信息:<{}>", byteArrayOutputStream.toString());
            return -5;
        }
        return 0;
    }

    @Override
    protected int bizTerminate(String s) {
        return 0;
    }

    /**
     * 关注小微商户服务平台的商户通过短信的方式告知商户交易信息
     *
     * @param sysParam       机构配置的短信发送开关
     * @param mchntOrderInfo 商户订单
     * @param txnInfo        txnInfo
     * @throws Exception 异常
     */
    private void mchntSmsNotice(SysParam sysParam, MchntOrderInfo mchntOrderInfo, TxnInfo txnInfo) throws Exception {

        if (null != sysParam && AppParamConstant.YES.equals(sysParam.getParamValue().trim())) {
            TxnNoticeInfoMapper txnNoticeInfoMapper = new TxnNoticeInfoMapperImpl();
            /* 获取商户基本信息 */
            MchntService mchntService = new MchntServiceImpl();
            MchntInfo mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
            if (null != mchntInfo && AppParamConstant.YES.equals(mchntInfo.getSmsSendFlag())) {
                /* 检查是否已发送过短信 */
                DubboService dubboService = new DubboServiceImpl();
                GeneralSmsNoticeRequest generalSMSNoticeRequest = initSmsNoticeMsg(mchntInfo, mchntOrderInfo, txnInfo);
                if (null != generalSMSNoticeRequest) {
                    Result<GeneralSmsNoticeResponse> smsResult = (Result<GeneralSmsNoticeResponse>) dubboService.callDubboService(ShareServiceConstant.SMS_PLAT_SEND_SERVICE, ShareServiceConstant.SMS_PLAT_SEND_METHOD, generalSMSNoticeRequest);
                    if (null == smsResult || !smsResult.isSuccess() || !OltpRpcdEnum.TRANS_SUCCESS.getRespCode().equals(smsResult.getResult().getRespCode())) {
                        rglog.error("调用短信平台发送短信通知失败:{}", JSON.toJSONString(generalSMSNoticeRequest));
                    }
                    /* 登记短信发送记录 */
                    TxnNoticeInfo txnNoticeInfo = initTxnNoticeInfo(mchntOrderInfo, txnInfo, "01", mchntInfo.getContactPhone(), generalSMSNoticeRequest.getSmsContent());
                    txnNoticeInfo.setNoticeStaus("01");
                    int iReturnCode = txnNoticeInfoMapper.insertTxnNoticeInfo(txnNoticeInfo);
                    if (0 != iReturnCode) {
                        rglog.warn("登记短信通知信息失败:{},iReturnCode:<{}>", JSON.toJSONString(txnNoticeInfo), iReturnCode);
                    }
                }
            } else {
                rglog.info("商户:<{}>不存在或未开通发送短信通知功能", mchntOrderInfo.getMchntNo());
            }
        }
    }

    /**
     * 生成发送短信内容
     *
     * @param mchntInfo      商户信息
     * @param mchntOrderInfo 商户订单信息
     * @param txnInfo        交易信息
     * @return 短信消费对象
     * @throws Exception 异常
     */
    private GeneralSmsNoticeRequest initSmsNoticeMsg(MchntInfo mchntInfo, MchntOrderInfo mchntOrderInfo, TxnInfo txnInfo) throws Exception {
        GeneralSmsNoticeRequest generalSMSNoticeRequest = new GeneralSmsNoticeRequest();
        Header header = new Header();
        header.setVersion("1.0.0");
        header.setTransDate(DateUtil.getCurrentDate());
        header.setTransTime(DateUtil.getCurrentTime());
        header.setTxnNum("00450000000E01");
        header.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        header.setInstId(mchntInfo.getInstId());
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setChanlId(AppParamConstant.SYS_ID);
        header.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntInfo.getInstId()));
        generalSMSNoticeRequest.setHeader(header);
        generalSMSNoticeRequest.setRealtimeFlag(AppParamConstant.YES);
        generalSMSNoticeRequest.setAppointTime("0");
        List<String> phoneNoList = new ArrayList<>();
        phoneNoList.add(mchntInfo.getContactPhone());
        generalSMSNoticeRequest.setPhoneList(phoneNoList);
        generalSMSNoticeRequest.setTemplateId("S01");
        /* 拼装短信内容 */
        if (TransTypeEnum.PAY.equals(TransTypeEnum.getTransType(txnInfo.getSrcTxnAuthCfg().getTxnNum()))) {
            String msgContent = "(辅助通知)尊敬的用户您于" + mchntOrderInfo.getTxnTime() +
                    "发生" + txnInfo.getSrcTxnAuthCfg().getTxnName() +
                    "交易" + mchntOrderInfo.getRealSettleAmt() + "元，" +
                    "订单:" + mchntOrderInfo.getMchntOrderId();
            generalSMSNoticeRequest.setSmsContent(msgContent);
        } else if (TransTypeEnum.REFUND.equals(TransTypeEnum.getTransType(txnInfo.getSrcTxnAuthCfg().getTxnNum()))) {
            String msgContent = "(辅助通知)尊敬的用户您于" + mchntOrderInfo.getTxnTime() +
                    "发生" + txnInfo.getSrcTxnAuthCfg().getTxnName() +
                    "交易" + mchntOrderInfo.getRealSettleAmt() + "元";
            MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
            List<MchntOrderInfo> mchntOrderInfoList = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(mchntOrderInfo.getInstId(), mchntOrderInfo.getOrigSysSeqNum());
            if (null != mchntOrderInfoList && !mchntOrderInfoList.isEmpty()) {
                msgContent += "，原订单:" + mchntOrderInfoList.get(0).getMchntOrderId();
            }
            generalSMSNoticeRequest.setSmsContent(msgContent);
        } else {
            rglog.info("非支付或者退款交易，不发送短信!");
            return null;
        }
        return generalSMSNoticeRequest;
    }


    /**
     * 语音推送
     *
     * @param mchntOrderInfo  商户订单信息
     * @param devBindInfoList 设备绑定关系
     * @param payOrderInfo    支付订单信息
     * @param txnInfo         交易配置信息
     * @throws Exception 异常
     */
    private void voiceDevNotice(MchntOrderInfo mchntOrderInfo, List<DevBindInfo> devBindInfoList, PayOrderInfo payOrderInfo, TxnInfo txnInfo) throws Exception {
        /* 获取当前交易用户对应绑定的语音设备 */
        rglog.debug("语音推送");
        if (!StringUtil.isEmptyOrNull(mchntOrderInfo.getUserId())) {
            devBindInfoList = devBindInfoList.stream().filter(item -> item.getBindUserId().trim().equals(mchntOrderInfo.getUserId().trim())).collect(Collectors.toList());
            if (devBindInfoList.isEmpty()) {
                rglog.info("当前用户<{}>没有绑定语音设备,不进行语音推送!", mchntOrderInfo.getUserId());
                return;
            }
        }
        /* 非支付类交易不进行语音播报推送 */
        if (!TransTypeEnum.PAY.equals(TransTypeEnum.getTransType(txnInfo.getSrcTxnAuthCfg().getTxnNum()))) {
            rglog.warn("当前交易<{}-{}>为非支付类交易，不进行语音推送!", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            return;
        }
        /* 推送语音设备类型推送语音消息 */
        DubboService dubboService = new DubboServiceImpl();
        for (DevBindInfo devBindInfo : devBindInfoList) {
            if ("01".equals(devBindInfo.getBindDevType())) {
                /* 手机设备语音推送 */
                //TODO 微信动账提醒
            } else if ("02".equals(devBindInfo.getBindDevType()) && !StringUtil.isEmptyOrNull(devBindInfo.getMsgPushKey())) {
                /* 语音设备语音推送 */
                switch (devBindInfo.getMsgPushKey().trim()) {
                    case "01":
                        /* 阿里云设备推送 */
                        AliyunIotMsgPushRequest aliyunIotMsgPushRequest = new AliyunIotMsgPushRequest();
                        aliyunIotMsgPushRequest.setProductKey(devBindInfo.getBindDevModel());
                        aliyunIotMsgPushRequest.setDeviceName(devBindInfo.getBindDevBrand());
                        aliyunIotMsgPushRequest.setVoiceAmt(mchntOrderInfo.getOrderAmt());
                        aliyunIotMsgPushRequest.setVoiceMsg("");
                        dubboService.asynCallDubboService(ShareServiceConstant.MSG_PUSH_SERVICE, ShareServiceConstant.ALIYUN_MSG_PUSH_METHOD, aliyunIotMsgPushRequest, null);
                        break;
                    case "02":
                        /* 信雅达设备推送 */
                        SunyardVoicePushRequest sunyardVoicePushRequest = new SunyardVoicePushRequest();
                        Header header = new Header();
                        ConvertUtil.convertOutput(header);
                        sunyardVoicePushRequest.setHeader(header);
                        sunyardVoicePushRequest.setPayOrderId(mchntOrderInfo.getSysSeqNum());
                        sunyardVoicePushRequest.setMchntNo(mchntOrderInfo.getMchntNo());
                        sunyardVoicePushRequest.setTermNo(mchntOrderInfo.getTermNo());
                        sunyardVoicePushRequest.setPayStatus("1".equals(mchntOrderInfo.getTransStatus()) ? "00" : "99");
                        if (null != payOrderInfo) {
                            switch (payOrderInfo.getPayType()) {
                                case "02":
                                    sunyardVoicePushRequest.setPayType("07");
                                    break;
                                case "03":
                                    sunyardVoicePushRequest.setPayType("08");
                                    break;
                                case "04":
                                    sunyardVoicePushRequest.setPayType("01");
                                    break;
                                default:
                                    sunyardVoicePushRequest.setPayType("00");
                                    break;
                            }
                            sunyardVoicePushRequest.setPayerInfo(payOrderInfo.getPayerAcctInfo());
                        }
                        sunyardVoicePushRequest.setPayTime(mchntOrderInfo.getTxnDate() + mchntOrderInfo.getTxnTime());
                        sunyardVoicePushRequest.setPayAmt(mchntOrderInfo.getOrderAmt());
                        sunyardVoicePushRequest.setProductKey(devBindInfo.getBindDevModel());
                        sunyardVoicePushRequest.setDeviceName(devBindInfo.getBindDevBrand());
                        dubboService.asynCallDubboService(ShareServiceConstant.MSG_PUSH_SERVICE, ShareServiceConstant.SUNYARD_VOICE_PUSH_METHOD, sunyardVoicePushRequest, null);
                        break;
                    case "03":
                        /* 意税设备推送 */
                        InspiryVoicePushRequest inspiryVoicePushRequest = new InspiryVoicePushRequest();
                        inspiryVoicePushRequest.setProductKey(devBindInfo.getBindDevModel());
                        inspiryVoicePushRequest.setDeviceName(devBindInfo.getBindDevBrand());
                        inspiryVoicePushRequest.setDeviceId(devBindInfo.getBindDevId());
                        inspiryVoicePushRequest.setPayAmt(mchntOrderInfo.getOrderAmt());
                        if (TransTypeEnum.PAY.equals(TransTypeEnum.getTransType(txnInfo.getSrcTxnAuthCfg().getTxnNum()))) {
                            inspiryVoicePushRequest.setPayType("0");
                        } else if (TransTypeEnum.CANCEL.equals(TransTypeEnum.getTransType(txnInfo.getSrcTxnAuthCfg().getTxnNum()))) {
                            inspiryVoicePushRequest.setPayType("1");
                        } else if (TransTypeEnum.REFUND.equals(TransTypeEnum.getTransType(txnInfo.getSrcTxnAuthCfg().getTxnNum()))) {
                            inspiryVoicePushRequest.setPayType("2");
                        }
                        if (Objects.requireNonNull(payOrderInfo).getPayType().equals("02")) {
                            inspiryVoicePushRequest.setPayType("2");
                        } else if (payOrderInfo.getPayType().equals("03")) {
                            inspiryVoicePushRequest.setPayType("1");
                        } else if (payOrderInfo.getPayType().equals("04")) {
                            inspiryVoicePushRequest.setPayType("3");
                        } else {
                            inspiryVoicePushRequest.setPayType("0");
                        }
                        inspiryVoicePushRequest.setPaySeqNum(mchntOrderInfo.getSysSeqNum());
                        dubboService.asynCallDubboService(ShareServiceConstant.MSG_PUSH_SERVICE, ShareServiceConstant.INSPIRY_VOICE_PUSH_METHOD, inspiryVoicePushRequest, null);
                        break;
                }
            } else {
                rglog.warn("不支持的语音设置类型:<{}>", devBindInfo.getBindDevType());
            }
        }
    }

    /**
     * 微信公众号消息推送
     *
     * @param mchntOrderInfo 商户订单信息
     * @param openIdList     推送用户列表
     * @param txnInfo        交易信息
     * @param payOrderInfo   支付订单信息
     * @throws Exception 异常
     */
    private void mchntWechatNotice(MchntOrderInfo mchntOrderInfo, List<String> openIdList, TxnInfo txnInfo, PayOrderInfo payOrderInfo) throws Exception {

        rglog.debug("微信公众号消息推送");
        String payerAcctInfo = "";
        if (!StringUtil.isEmptyOrNull(payOrderInfo.getPayerAcctInfo())) {
            if ("UPWX".equals(payOrderInfo.getMsgDstId())) {
                payerAcctInfo = "微信用户";
            } else if ("UPAL".equals(payOrderInfo.getMsgDstId())) {
                //支付宝已脱敏
                payerAcctInfo = payOrderInfo.getPayerAcctInfo();
            } else {
                payerAcctInfo = SensitiveDataUtil.desensitization("2", payOrderInfo.getPayerAcctInfo()).split("\\|")[0];
            }
        }
        final String payerInfo = payerAcctInfo;

        /* 根据交易类型进行推送 */
        cc.rengu.igas.channel.wechat.facade.base.Header header = new cc.rengu.igas.channel.wechat.facade.base.Header();
        ConvertUtil.convertOutput(header);
        header.setTxnNum("financialtrans");
        List<Object> wechatPushMsgList = new ArrayList<>();
        String pushMechodName = ShareServiceConstant.FINANCIAL_TRANS_MSG_PUSH;
        if (TransTypeEnum.REFUND.equals(TransTypeEnum.getTransType(txnInfo.getSrcTxnAuthCfg().getTxnNum()))) {
            /* 退款类交易推送 */
            pushMechodName = ShareServiceConstant.WECHAT_REFUND_MSG_PUSH;
            header.setTxnNum("refundpush");
            openIdList.forEach(item -> {
                RefundMsgPushRequest wechatPushMsgRequest = new RefundMsgPushRequest();

                rglog.debug("查询原支付交易,原支付交易流水为<{}>", mchntOrderInfo.getOrigSysSeqNum());
                List<MchntOrderInfo> mchntOrderInfoList = new ArrayList<>();
                try {
                    MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
                    mchntOrderInfoList = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(mchntOrderInfo.getInstId(), mchntOrderInfo.getOrigSysSeqNum());
                    wechatPushMsgRequest.setPayerInfo(payerInfo);
                    //获取退款交易对应的原支付交易
                    PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
                    List<PayOrderInfo> payOrderInfoLists = payOrderInfoMapper.selectPayOrderInfoBySysSeqNum(mchntOrderInfo.getInstId(), mchntOrderInfo.getOrigSysSeqNum());
                    if (!CollectionUtils.isEmpty(payOrderInfoLists)) {
                        rglog.debug("原交易支付信息<{}>", payOrderInfoLists.get(0).getPayerAcctInfo());
                        if (!StringUtil.isEmptyOrNull(payOrderInfoLists.get(0).getPayerAcctInfo())) {
                            if ("00".equals(payOrderInfoLists.get(0).getPayType()) || "01".equals(payOrderInfoLists.get(0).getPayType()) || "04".equals(payOrderInfoLists.get(0).getPayType())) {
                                String payerAcctInfos = SensitiveDataUtil.desensitization("2", payOrderInfoLists.get(0).getPayerAcctInfo()).split("\\|")[0];
                                wechatPushMsgRequest.setPayerInfo(payerAcctInfos);

                            } else {
                                wechatPushMsgRequest.setPayerInfo(payOrderInfoLists.get(0).getPayerAcctInfo());
                            }
                        }
                    }

                } catch (Exception e) {
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
                }
                /*退款交易推送需上送原交易订单号*/
                wechatPushMsgRequest.setMchntOrderId(mchntOrderInfoList.get(0).getMchntOrderId());
                wechatPushMsgRequest.setHeader(header);
                wechatPushMsgRequest.setTransAmt(mchntOrderInfo.getRealSettleAmt());
                wechatPushMsgRequest.setTransTime(DateUtil.dateStringFormatConvert(mchntOrderInfo.getTxnDate() + mchntOrderInfo.getTxnTime(), "yyyyMMddHHmmss", "yyyy-MM-dd HH:mm:ss"));
                wechatPushMsgRequest.setChannelId(ChannelEnum.WXZF.getChannelType());
                wechatPushMsgRequest.setPayType(txnInfo.getSrcTxnAuthCfg().getTxnName().trim());
                wechatPushMsgRequest.setOpenId(item);

                wechatPushMsgList.add(wechatPushMsgRequest);
            });
        } else if (TransTypeEnum.CANCEL.equals(TransTypeEnum.getTransType(txnInfo.getSrcTxnAuthCfg().getTxnNum()))) {
            /* 撤销类交易推送 */
            pushMechodName = ShareServiceConstant.WEChAT_CANCLE_MSG_PUSH;
            header.setTxnNum("cancelpush");
            openIdList.forEach(item -> {
                CancelMsgPushRequest wechatPushMsgRequest = new CancelMsgPushRequest();
                wechatPushMsgRequest.setMchntOrderId(mchntOrderInfo.getMchntOrderId());
                wechatPushMsgRequest.setHeader(header);
                wechatPushMsgRequest.setTransAmt(mchntOrderInfo.getRealSettleAmt());
                wechatPushMsgRequest.setTransTime(DateUtil.dateStringFormatConvert(mchntOrderInfo.getTxnDate() + mchntOrderInfo.getTxnTime(), "yyyyMMddHHmmss", "yyyy-MM-dd HH:mm:ss"));
                wechatPushMsgRequest.setChannelId(ChannelEnum.WXZF.getChannelType());
                wechatPushMsgRequest.setPayType(txnInfo.getSrcTxnAuthCfg().getTxnName().trim());
                wechatPushMsgRequest.setOpenId(item);
                wechatPushMsgRequest.setPayerInfo(payerInfo);
                wechatPushMsgList.add(wechatPushMsgRequest);
            });
        } else {
            openIdList.forEach(item -> {
                /* 支付类交易推送 */
                FinancialTransMsgPushRequest wechatPushMsgRequest = new FinancialTransMsgPushRequest();
                wechatPushMsgRequest.setMchntOrderId(mchntOrderInfo.getMchntOrderId());
                /*上送商户订单表中商户实际收款金额*/
                wechatPushMsgRequest.setHeader(header);
                wechatPushMsgRequest.setTransAmt(mchntOrderInfo.getRealSettleAmt());
                wechatPushMsgRequest.setTransTime(DateUtil.dateStringFormatConvert(mchntOrderInfo.getTxnDate() + mchntOrderInfo.getTxnTime(), "yyyyMMddHHmmss", "yyyy-MM-dd HH:mm:ss"));
                wechatPushMsgRequest.setChannelId(ChannelEnum.WXZF.getChannelType());
                wechatPushMsgRequest.setPayType(txnInfo.getSrcTxnAuthCfg().getTxnName().trim());
                wechatPushMsgRequest.setTitleType("X03");
                wechatPushMsgRequest.setOpenId(item);
                wechatPushMsgRequest.setPayerInfo(payerInfo);
                wechatPushMsgRequest.setUrlParam(Base64.encodeBase64String(("mchntNo=".concat(mchntOrderInfo.getMchntNo()).concat("&mchntOrderId=").concat(mchntOrderInfo.getMchntOrderId()).concat("&origTraceNo=").concat(mchntOrderInfo.getSysSeqNum()).concat("&origTraceNo=").concat(mchntOrderInfo.getSysSeqNum())).getBytes()));
                wechatPushMsgList.add(wechatPushMsgRequest);
            });
        }
        DubboService dubboService = new DubboServiceImpl();
        for (Object item : wechatPushMsgList) {
            dubboService.asynCallDubboService(ShareServiceConstant.WECHAT_MSG_PUSH_SERVICE, pushMechodName, item, ShareServiceConstant.TRANS_SMS_NOTICE_SERVICE, 3, 1, 60);
        }
    }

    /**
     * 推送交易结果给商户服务后台或者商户服务H5
     *
     * @param userOrderInfo 用户订单信息
     */
    private void transResultNoticeToMchntSystem(UserOrderInfo userOrderInfo, String pushMsgContent, TxnInfo txnInfo) throws Exception {
        rglog.debug("推送交易结果给商户服务后台或者商户服务H5");
        DubboService dubboService = new DubboServiceImpl();
        Header header = new Header();
        header.setSrcSysId("IGAS");
        header.setChanlId(userOrderInfo.getTransChannelId());
        header.setVersion(ShareParamConstant.DUBBO_VSERSION);
        header.setTransDate(userOrderInfo.getTxnDate());
        header.setTransTime(userOrderInfo.getTxnTime());
        header.setBizType(ShareParamConstant.DUBBO_DEFAULT_BIZ_TYPE);
        header.setInstId(userOrderInfo.getInstId());
        header.setTraceNo(DateUtil.getCurrentDateTime("yyyyMMddHHmmss") + RandomUtil.randomCharNumberString(16));
        TransResultNoticeRequest transResultNoticeRequest = new TransResultNoticeRequest();
        transResultNoticeRequest.setContent(pushMsgContent);

        /*获取商户订单信息*/
        MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
        List<MchntOrderInfo> mchntOrderInfoList = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(userOrderInfo.getInstId(), userOrderInfo.getSysSeqNum());
        if (null == mchntOrderInfoList) {
            rglog.error("获取商户订单信息失败，不发送异步通知");
            return;
        }

        /*查询商户基本信息*/
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(mchntOrderInfoList.get(0).getInstId(), mchntOrderInfoList.get(0).getMchntNo());
        if (null == mchntInfo) {
            rglog.error("获取商户基本信息失败，不发送异步通知");
            return;
        }

        if (!StringUtil.isEmptyOrNull(userOrderInfo.getNotifyBackUrl())) {
            rglog.debug("推送给商户后台系统");
            header.setTxnNum("T00CP900");
            transResultNoticeRequest.setHeader(header);
            transResultNoticeRequest.setNoticeUrl(userOrderInfo.getNotifyBackUrl());

            /* 登记发送记录 */
            TxnNoticeInfoMapper txnNoticeInfoMapper = new TxnNoticeInfoMapperImpl();
            TxnNoticeInfo txnNoticeInfo = initTxnNoticeInfo(mchntOrderInfoList.get(0), txnInfo, "04", mchntInfo.getContactPhone(), JSON.toJSONString(pushMsgContent));
            txnNoticeInfo.setNoticeStaus("00");
            int iReturnCode = txnNoticeInfoMapper.insertTxnNoticeInfo(txnNoticeInfo);
            if (0 != iReturnCode) {
                rglog.warn("异步通知登记流水失败:{},iReturnCode:<{}>", JSON.toJSONString(txnNoticeInfo), iReturnCode);
            }
            rglog.debug("支付结果通知推送");
            dubboService.asynCallDubboService(ShareServiceConstant.MSG_PUSH_SERVICE, ShareServiceConstant.MCHNT_TRANS_RESULT_NOTICE,
                    transResultNoticeRequest, null, 3, 1, 60);
        }
    }

    /**
     * 拼装商户后台或者H5消息推送内容
     *
     * @param mchntOrderInfoList 商户订单信息
     * @param payOrderInfo       支付订单信息
     * @param respDesc           错误描述
     * @param txnInfo            交易信息
     * @return 消息推送内容
     */
    private String convMchntPushMsg(List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo, String respDesc, TxnInfo txnInfo, UserOrderInfo userOrderInfo) {
        TransNoticeBean transNoticeBean = new TransNoticeBean();
        // 平台商户上送平台商户号
        if (!StringUtil.isEmptyOrNull(userOrderInfo.getGroupMchntNo())) {
            transNoticeBean.setMchntNo(userOrderInfo.getGroupMchntNo());
        } else {
            transNoticeBean.setMchntNo(mchntOrderInfoList.get(0).getMchntNo());
        }

        transNoticeBean.setMchntOrderId(userOrderInfo.getMchntOrderId());
        transNoticeBean.setPaySeqNum(userOrderInfo.getSysSeqNum());
        transNoticeBean.setTxnName(txnInfo.getSrcTxnAuthCfg().getTxnName());
        transNoticeBean.setTransDate(userOrderInfo.getTxnDate());
        transNoticeBean.setTransTime(userOrderInfo.getTxnTime());
        transNoticeBean.setOrderCcy(userOrderInfo.getOrderCcy());
        transNoticeBean.setOrderAmt(userOrderInfo.getOrderAmt());
        transNoticeBean.setPayType(convPayOrderPayType(payOrderInfo));
        transNoticeBean.setPayStatus(userOrderInfo.getTransStatus());
        transNoticeBean.setRespCode("00000000");
        transNoticeBean.setRespDesc(respDesc);
        return JSON.toJSONString(transNoticeBean);
    }

    /**
     * 获取消息推送的用户列表
     *
     * @param mchntBindInfoList 商户绑定关系
     * @return 消息推送用户列表
     */
    private List<String> convMsgPushUsers(List<MchntBindInfo> mchntBindInfoList) {
        List<String> msgPushUsersList = new ArrayList<>();
        for (MchntBindInfo mchntBindInfo : mchntBindInfoList) {
            if (!StringUtil.isEmptyOrNull(mchntBindInfo.getMsgPushUsers())) {
                rglog.debug("商户设备绑定关系的关联消息推送用户为:<{}>", mchntBindInfo.getMsgPushUsers());
                String[] userArrary = mchntBindInfo.getMsgPushUsers().split(",");
                List<String> userList = Arrays.stream(userArrary).collect(Collectors.toList());
                msgPushUsersList.addAll(userList);
            }
            msgPushUsersList.add(mchntBindInfo.getBindUserId());
        }
        return msgPushUsersList.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 拼装支付方式字符串
     *
     * @param payOrderInfo 支付订单表信息
     * @return 支付方式组合
     */
    private String convPayOrderPayType(PayOrderInfo payOrderInfo) {
        StringBuilder stringBuilder = new StringBuilder();
        Set<String> payTypesSet = new HashSet<>();
        if ("*".equals(payOrderInfo.getPayType().trim())) {
            payTypesSet.add("*");
        } else {
            payTypesSet.add(payOrderInfo.getPayType().trim());
        }
        for (String key : payTypesSet) {
            stringBuilder.append(key.trim());
            stringBuilder.append("|");
        }
        String payTypes = stringBuilder.toString();
        return payTypes.substring(0, payTypes.length() - 1);
    }

    /**
     * 初始化消息推送信息
     *
     * @param mchntOrderInfo 商户订单信息
     * @param txnInfo        交易信息
     * @param noticeType     通知类型（00-公众号推送、01-短信推送、02-手机银行推送、03-语音设备推送）
     * @param noticeTarget   通知对象
     * @param noticeMsg      通知内容
     * @return 交易通知信息表中信息
     */
    private TxnNoticeInfo initTxnNoticeInfo(MchntOrderInfo mchntOrderInfo, TxnInfo txnInfo, String noticeType, String noticeTarget, String noticeMsg) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /* 登记微信公众号消息推送失败记录 */
        TxnNoticeInfo txnNoticeInfo = new TxnNoticeInfo();
        txnNoticeInfo.setInstId(mchntOrderInfo.getInstId());
        txnNoticeInfo.setSysSeqNum(mchntOrderInfo.getSysSeqNum());
        txnNoticeInfo.setMchntNo(mchntOrderInfo.getMchntNo());
        txnNoticeInfo.setNoticeType(noticeType);
        txnNoticeInfo.setNoticeTarget(noticeTarget);
        txnNoticeInfo.setMchntOrderId(mchntOrderInfo.getMchntOrderId());
        txnNoticeInfo.setMsgSrcId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SRC_SYS_ID));
        txnNoticeInfo.setTransChannelId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_CHANNEL_ID));
        txnNoticeInfo.setTxnNum(txnInfo.getSrcTxnAuthCfg().getTxnNum());
        txnNoticeInfo.setBizType(txnInfo.getSrcTxnAuthCfg().getBizType());
        txnNoticeInfo.setTxnDate(mchntOrderInfo.getTxnDate());
        txnNoticeInfo.setTxnTime(mchntOrderInfo.getTxnTime());
        txnNoticeInfo.setOrderAmt(mchntOrderInfo.getOrderAmt());
        txnNoticeInfo.setTryMaxTimes(3);
        txnNoticeInfo.setTryTimes(1);
        txnNoticeInfo.setNoticeStaus("00");
        txnNoticeInfo.setNoticeMsg(noticeMsg);
        txnNoticeInfo.setNoticeTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        return txnNoticeInfo;
    }
}
